"""
DjangoBlog 评论功能视图模块
处理用户评论的提交、验证和保存
基于Django的FormView实现评论表单处理
"""

from django.core.exceptions import ValidationError
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
from django.views.generic.edit import FormView

from accounts.models import BlogUser
from blog.models import Article
from .forms import CommentForm
from .models import Comment


class CommentPostView(FormView):
    """
    评论提交视图
    处理用户对文章的评论提交，支持父评论（回复）功能
    继承自Django的FormView，自动处理表单验证和提交
    """
    
    form_class = CommentForm  # 使用的评论表单类
    template_name = 'blog/article_detail.html'  # 评论提交后重定向的模板

    @method_decorator(csrf_protect)  # 添加CSRF保护，防止跨站请求伪造攻击
    def dispatch(self, *args, **kwargs):
        """
        重写请求分发方法
        所有请求都会先经过此方法，确保CSRF保护生效
        """
        return super(CommentPostView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        """
        处理GET请求
        防止直接通过GET方式访问评论提交页面，重定向到文章详情页
        """
        article_id = self.kwargs['article_id']  # 从URL参数获取文章ID
        article = get_object_or_404(Article, pk=article_id)  # 获取文章对象，不存在则返回404
        url = article.get_absolute_url()  # 获取文章的绝对URL
        return HttpResponseRedirect(url + "#comments")  # 重定向到文章详情页的评论区域

    def form_invalid(self, form):
        """
        表单验证失败的处理逻辑
        当用户提交的评论数据不符合要求时执行
        """
        article_id = self.kwargs['article_id']  # 获取文章ID
        article = get_object_or_404(Article, pk=article_id)  # 获取文章对象

        # 重新渲染文章详情页，显示表单错误信息
        return self.render_to_response({
            'form': form,  # 包含错误信息的表单
            'article': article  # 文章对象，用于显示文章内容
        })

    def form_valid(self, form):
        """
        表单验证成功后的处理逻辑
        保存评论数据到数据库，处理父子评论关系
        """
        # 获取当前登录用户信息
        user = self.request.user  # 从请求中获取用户对象
        author = BlogUser.objects.get(pk=user.pk)  # 根据用户ID获取完整的用户对象
        
        # 获取评论对应的文章信息
        article_id = self.kwargs['article_id']  # 从URL参数获取文章ID
        article = get_object_or_404(Article, pk=article_id)  # 获取文章对象

        # 检查文章是否允许评论
        if article.comment_status == 'c' or article.status == 'c':
            # 文章评论已关闭或文章状态异常，抛出验证错误
            raise ValidationError("该文章评论已关闭.")
        
        # 创建评论对象但不立即保存（save(False)）
        comment = form.save(False)
        comment.article = article  # 设置评论所属的文章
        
        # 获取博客设置，判断评论是否需要审核
        from djangoblog.utils import get_blog_setting
        settings = get_blog_setting()  # 获取博客全局设置
        
        # 如果设置为不需要审核，直接启用评论
        if not settings.comment_need_review:
            comment.is_enable = True  # 设置评论为启用状态
        
        comment.author = author  # 设置评论作者

        # 处理父评论（回复功能）
        if form.cleaned_data['parent_comment_id']:
            # 如果提供了父评论ID，说明这是对某条评论的回复
            parent_comment = Comment.objects.get(
                pk=form.cleaned_data['parent_comment_id'])  # 获取父评论对象
            comment.parent_comment = parent_comment  # 设置父子评论关系

        # 保存评论到数据库
        comment.save(True)
        
        # 重定向到文章详情页，并定位到新提交的评论位置
        return HttpResponseRedirect(
            "%s#div-comment-%d" %  # 使用锚点定位到具体的评论div
            (article.get_absolute_url(), comment.pk))  # 文章URL + 评论ID锚点